Schema: per-definition parse API and lenient subschema mode - #62
Merged
Conversation
Subschema subentries publish bare parenthesized definitions, and a live server's schema cannot be fixed by the consumer — so alongside the strict slapd.conf file parser there is now: - LdapAttributeType.Parse / LdapObjectClass.Parse: strict single-definition parsing (RFC 4512 grammar; numeric OID, no unknown keywords, no trailing text). Bare definitions have no objectidentifier macro context. - LdapSchema.ParseSubschema: lenient aggregate over attributeTypes / objectClasses values. A definition that fails to parse degrades into UnparsedDefinitions (raw text + error + kind) instead of blanking the schema; unknown non-X- keywords inside a definition are skipped (a bare word is left in place — it is more likely the next keyword than a value). X- extensions are captured, as in file mode. The strict file parser is unchanged: unknown keywords still throw, matching slapd's own rejection of them. Proven against real OpenLDAP 2.6 subschema output two ways: a committed fixture captured from a live slapd 2.6.10 (tools/capture-subschema-fixture.ps1, docker-based; 268 attribute types / 62 object classes, zero unparsed), and a new differential test that starts slapd on an ldapi socket and reads cn=Subschema live. slapd's parent process exits only once the listener is ready and the detached child releases inherited pipes — both verified empirically in a container before relying on them. Closes #60. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… floor From adversarial review of the previous commit (2 of 6 findings confirmed, 1 partially; the rest refuted with evidence): - The fixture's "2.6" was a filename claim with no runtime witness — the exact mislabeled-version class this repo has been burned by. The capture script now writes the answering slapd's version line as the fixture's first-line comment and fails closed if it is not 2.6; the fixture test asserts that witness, so a drifted recapture cannot silently relabel another version as 2.6. Fixture regenerated by the updated script (slapd 2.6.10, same 268/62/33 definitions). - The unknown-keyword skip heuristic's bare-word case was untested; a new test pins the deliberate tradeoff (bare word = next keyword) and its rationale. - The live differential test asserted a floor on attribute types but not object classes; now both, matching the fixture test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The previous commit's comment claimed a vendor bare value colliding with a standard keyword "mis-parses under either heuristic" — false: the consume-one-token alternative parses that exact shape correctly. Each heuristic has exactly one of the two blind spots. Rewritten to say so, with a test documenting the chosen heuristic's blind spot (NAME capturing the word SYNTAX) instead of leaving that mode untested, and the mechanism- distinguishing role correctly attributed to the flag-before-keyword test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #60.
What
Subschema subentries publish bare parenthesized definitions, and a live server's schema cannot be fixed by the consumer. Alongside the strict slapd.conf file parser there is now:
LdapAttributeType.Parse/LdapObjectClass.Parse— strict single-definition parsing (RFC 4512 grammar: numeric OID, no unknown keywords, no trailing text; noobjectidentifiermacro context, which is a schema-file concept).LdapSchema.ParseSubschema— lenient aggregate overattributeTypes/objectClassesvalues. A definition that fails to parse degrades intoUnparsedDefinitions(raw text + error + kind) instead of blanking the schema; unknown non-X-keywords inside a definition skip rather than failing it (X-extensions are captured, as in file mode). The skip heuristic leaves bare words in place — the flag-before-keyword shape is the realistic vendor pattern — and its one blind spot (a bare value colliding with a standard keyword) is documented by a dedicated test rather than hidden.The strict file parser is unchanged: unknown keywords still throw, matching slapd's own rejection of them.
Proven against real OpenLDAP two ways
tools/capture-subschema-fixture.ps1(docker; 268 attribute types / 62 object classes, zero unparsed). The fixture's first line is the answering slapd's version string, written by the script (which fails closed if the image stops shipping 2.6) and asserted by the fixture test — the filename's "2.6" cannot silently drift.cn=Subschemalive. slapd's parent process exits only once the listener is ready, and the detached child releases inherited pipes — both verified empirically in a container before relying on them; the full differential suite was run in a Linux container (slapd 2.6.10, Ubuntu 24.04 base) and passed.Review
Two adversarial review rounds ran (independent reviewer models). Round 1: 6 findings, 3 accepted and fixed in
0cb03d3(fixture provenance witness, object-class floor in the live test, heuristic pinning test), 3 refuted with evidence. Round 2: 6 findings, 3 accepted and fixed inb557def(an overclaiming comment corrected, the blind-spot mode given a documenting test), 3 refuted. Public API changes reviewed deliberately and re-approved inPublicApi.Schema.approved.txt.Groundwork for #61 (
ldapSyntaxesvalues are already in the captured fixture;LdapSchemaDefinitionKindextends additively).